package com.weipu.common.util;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import android.text.TextUtils;
import android.util.Log;

import com.weipu.common.DXApplication;
import com.weipu.common.constants.Constant;
import com.weipu.common.facade.model.CatelogModel;
import com.weipu.common.facade.model.NewsCornerModel;
import com.weipu.common.facade.model.ProductModel;
import com.weipu.common.facade.model.config.CacheConfig;
import com.weipu.common.facade.model.config.CacheConfigModel;
import com.weipu.common.facade.model.config.ConfigUtil;

import static android.R.attr.type;

/**
 * 缓存辅助类 用于本地缓存设置 ，根据响应速度缓存使用内存>>本地数据库>>远程服务端
 * 
 * 考虑到设备性能及数据时效性，大部分数据通过直接通过服务端获取，少量使用本地数据库操作，极少量数据通过内存缓存
 * 
 * 功能支持：是否允许开启缓存，缓存失效时间，缓存数目等相关配置
 * 
 * @author zhl014
 */
public final class CacheUtil implements Serializable
{
    /**
     * SN
     */
    private static final long serialVersionUID = 8645565318925736932L;
    
    private static final String TAG = "CacheUtil";
    
    private static CacheUtil inst = new CacheUtil();//单例对象
    
    //全局开关 --begin
    private boolean enableLocalDBCache;//是否允许本地数据库缓存
    
    private boolean enablePreLoad;//是否允许预加载，异步数据缓存刷新会使用到
    
    private double preLoadRate; //预加载比率(相对超时时间)
    
    private boolean enableLocalMemCache;//是否允许本地内存缓存(总开关)
    
    private boolean enableLog;//是否允许打印log
    
    //全局开关 --end
    
    //模块配置对象 --begin
    
    //栏目缓存
    private CategoryCacheConfig categoryCacheCfg;
    
    //产品缓存(首页挂牌)
    private ProductModelConfig productCacheCfg;
    
    //广告缓存(首页)
    private BannerCacheConfig bannerCacheConfig;
    
    //促销缓存(Mall Directory)
    private PromotionCacheConfig promotionCacheConfig;
    
    //我的账号数据缓存
    private MyAccountCacheConfig myAccountCacheConfig;
    
    //每日消息缓存
    private DayMsgCacheConfig dayMsgCacheConfig;
    
    //模块配置对象 --end
    
    private CacheUtil()
    {
        enableLocalMemCache = true;//是否允许本地内存缓存
        enableLocalDBCache = true;//是否允许本地数据库缓存       
        enablePreLoad = true;//允许预加载
        preLoadRate = 0.25F;//预加载比率(相对超时时间)
        
        // 此处的初始化后续可通过外部进行构造函数传参指定以便动态控制
        categoryCacheCfg = new CategoryCacheConfig();
        categoryCacheCfg.setEnableMemCache(true);
        categoryCacheCfg.setExpireTime(60 * 60 * 1000);//60分钟
        
        //首页挂牌产品
        // 此处的初始化后续可通过外部进行构造函数传参指定以便动态控制
        productCacheCfg = new ProductModelConfig();
        productCacheCfg.setEnableMemCache(true);
        productCacheCfg.setExpireTime(30 * 60 * 1000);//30分钟
        
        //banner缓存
        bannerCacheConfig = new BannerCacheConfig();
        bannerCacheConfig.setEnableMemCache(true);
        bannerCacheConfig.setExpireTime(60 * 60 * 1000);//60分钟
        
        //promotion
        promotionCacheConfig = new PromotionCacheConfig();
        promotionCacheConfig.setEnableMemCache(true);
        promotionCacheConfig.setExpireTime(60 * 60 * 1000);//60分钟
        
        //myAccount
        myAccountCacheConfig = new MyAccountCacheConfig();
        myAccountCacheConfig.setEnableMemCache(true);
        myAccountCacheConfig.setExpireTime(30 * 60 * 1000);//30分钟
        
        //dayMsg
        dayMsgCacheConfig = new DayMsgCacheConfig();
        dayMsgCacheConfig.setEnableMemCache(true);
        dayMsgCacheConfig.setExpireTime(30 * 60 * 1000);//30分钟，暂无效
    }
    
    public boolean isEnableLog()
    {
        return enableLog;
    }
    
    /**
     * 是否允许 每日消息缓存 
     * @return
     */
    public boolean isEnableMessageDayMemCache()
    {
        if (!isEnableLocalMemCache() && !dayMsgCacheConfig.isEnableMemCache())
        {
            return false;
        }
        
        boolean isTimeExpire = true;//每日消息是否已经超过一天或以上
        
        String[] key = {"refreshTime"};
        HashMap<String, String> messageConfig = StringUtil.getConfig(DXApplication.getContext(), key);
        if (messageConfig != null && !"".equals(messageConfig.get("refreshTime")))
        {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String currentTime = sdf.format(new Date());
            String refreshTime = messageConfig.get("refreshTime");
            //出现Day的差异或超过指定超时时间
            if (!currentTime.equals(refreshTime))
            {
                isTimeExpire = true;
            }
        }
        
        return (!isTimeExpire);
    }
    
    /**
     * 全局内存缓存配置开关
     * @return
     */
    private boolean isEnableLocalMemCache()
    {
        return enableLocalMemCache && checkMemory();
    }
    
    /**
     * 是否允许 栏目数据缓存
     * @return
     */
    public boolean isEnableCategoryMemCache()
    {
        return isEnableLocalMemCache() && categoryCacheCfg.isEnableMemCache();
    }
    
    /**
     * 是否允许 促销数据缓存
     * @return
     */
    public boolean isEnablePromotionMemCache()
    {
        return isEnableLocalMemCache() && promotionCacheConfig.isEnableMemCache();
    }
    
    /**
     * 是否允许本地数据缓存
     * @return
     */
    public boolean isEnableLocaleDBCache()
    {
        return enableLocalDBCache && checkLocalDB();
    }
    
    /**
     * 是否允许 产品数据缓存
     * @return
     */
    public boolean isEnableProductMemCache()
    {
        return isEnableLocalMemCache() && productCacheCfg.isEnableMemCache();
    }
    
    /**
     * 是否允许 广告数据缓存
     * @return
     */
    public boolean isEnableBannerMemCache()
    {
        return isEnableLocalMemCache() && bannerCacheConfig.isEnableMemCache();
    }
    
    /**
     * 本地栏目缓存数据是否有效
     * @param model
     * @return
     */
    public boolean isCategoryModelHitCache(CatelogModel model)
    {
        if ((!isEnableCategoryMemCache() && !isEnableLocaleDBCache()) || null == model)
        {
            return false;
        }
        
        long udpateTime = model.getCacheUpdateTime();
        
        //当前时间与数据录入时间小于缓存失效时长则认为缓存有效
        return (System.currentTimeMillis() - udpateTime) < categoryCacheCfg.getExpireTime();
        
    }
    
    /**
     * 产品缓存数据是否有效
     * @param model
     * @param typeKey 产品类型key(首页4大挂牌会使用到)
     * @return
     */
    public boolean isProductHitCache(ProductModel model, String typeKey)
    {
        //按产品类型缓存配置
        if (!TextUtils.isEmpty(typeKey) && isEnableCategoryMemCache())
        {
            CacheConfig config = productCacheCfg.getConfigMapping().get(typeKey);
            
            if (null != config)
            {
                //指定类型的数据缓存关闭则产品缓存无效
                if (!config.isEnable())
                {
                    return false;
                }
            }
        }
        
        //默认产品级缓存配置
        if ((!isEnableProductMemCache() && !isEnableLocaleDBCache()) || null == model)
        {
            return false;
        }
        
        long udpateTime = model.getCacheUpdateTime();
        
        //当前时间与数据录入时间小于缓存失效时长则认为缓存有效
        return (System.currentTimeMillis() - udpateTime) < productCacheCfg.getExpireTime();
    }
    
    /**
     * 促销缓存数据是否有效
     * @param model
     * @param typeKey 产品类型key(首页4大挂牌会使用到)
     * @return
     */
    public boolean isPromotionHitCache(NewsCornerModel model)
    {
        if ((!isEnableBannerMemCache()) && !!isEnableLocaleDBCache())
        {
            return false;
        }
        
        long updateTime = model.getCacheUpdateTime();
        
        return (System.currentTimeMillis() - updateTime) < promotionCacheConfig.getExpireTime();
    }
    
    //根据缓存时间计算缓存异步刷新周期
    //缓存刷新周期为缓存周期时长25%
    //返回的返回周期越长则数据版本越新，但影响性能及用户体验
    private int getPreLoadPeriodByExpireTime(int cacheExpire)
    {
        return cacheExpire * (int)Math.round(preLoadRate * 100) / 100;
    }
    
    /**
     * 是否需要刷新缓存
     * @return
     */
    public boolean isNeedRefreshCache(CatelogModel model)
    {
        //是否允许预加载
        if (!enablePreLoad)
        {
            return false;
        }
        
        //本地缓存开关已经关闭
        if ((!isEnableCategoryMemCache() && !isEnableLocaleDBCache()) || null == model)
        {
            return false;
        }
        
        long udpateTime = model.getCacheUpdateTime();
        
        //缓存的数据超过{preLoadPerod}则认为需要预加载
        return (System.currentTimeMillis() - udpateTime) > getPreLoadPeriodByExpireTime(categoryCacheCfg.getExpireTime());
        
    }
    
    /**
     * 是否需要刷新缓存
     * @return
     */
    public boolean isNeedRefreshCache(NewsCornerModel model)
    {
        //是否允许预加载
        if (!enablePreLoad)
        {
            return false;
        }
        
        //本地缓存开关已经关闭
        if ((!isEnablePromotionMemCache() && !isEnableLocaleDBCache()) || null == model)
        {
            return false;
        }
        
        long udpateTime = model.getCacheUpdateTime();
        
        //缓存的数据超过{preLoadPerod}则认为需要预加载
        return (System.currentTimeMillis() - udpateTime) > getPreLoadPeriodByExpireTime(promotionCacheConfig.getExpireTime());
        
    }
    
    /**
     * 是否需要刷新缓存
     * @return
     */
    public boolean isNeedRefreshCache(ProductModel model)
    {
        //是否允许预加载
        if (!enablePreLoad)
        {
            return false;
        }
        
        //本地缓存开关已经关闭
        if ((!isEnableProductMemCache() && !isEnableLocaleDBCache()) || null == model)
        {
            return false;
        }
        
        long udpateTime = model.getCacheUpdateTime();
        //备注：由于减小服务器压力 暂时取消预加载功能 by huangfei 20150523
        return false;
        //缓存的数据超过{preLoadPerod}则认为需要预加载
        //return (System.currentTimeMillis() - udpateTime) > getPreLoadPeriodByExpireTime(productCacheCfg.getExpireTime());
    }
    
    /**
     * 广告缓存数据是否有效
     * @param model
     * @return
     */
    public boolean isCacheEffective(String time)
    {
    	Logger.i(TAG, "categoryCacheCfg.getExpireTime():"+categoryCacheCfg.getExpireTime());
        long updateTime = Long.valueOf(time);
//        return (System.currentTimeMillis() - updateTime) < categoryCacheCfg.getExpireTime();
        return true;
    }
    
    /**
     * 返回单实例
     * 
     * @return
     */
    public static CacheUtil getInstance()
    {
        return inst;
    }
    
    static class CategoryCacheConfig extends BaseCfg
    {
        
    }
    
    static class ProductModelConfig extends BaseCfg
    {
        private HashMap<String, CacheConfig> configMapping;//详细缓存配置，可按照类型独立设置缓存
        
        ProductModelConfig()
        {
            configMapping = new HashMap<String, CacheConfig>();
        }
        
        public HashMap<String, CacheConfig> getConfigMapping()
        {
            return configMapping;
        }
        
        void setConfigMapping(HashMap<String, CacheConfig> configMapping)
        {
            this.configMapping = configMapping;
        }
    }
    
    /**
     *  是否允许预加载数据
     * @return
     */
    public boolean isEnablePreLoad()
    {
        return enablePreLoad;
    }
    
    /**
     * 更新缓存配置信息
     * @param model
     * @return
     */
    public CacheUtil updateConfig(CacheConfigModel model)
    {
        if (null == model)
        {
            return this;
        }
        
        Logger.d(TAG, "update config: " + model.toString());
        
        //TODO CacheUtil
        //        private CategoryCacheConfig categoryCacheCfg;
        //        
        //        private ProductModelConfig productCacheCfg;
        //        
        //        private BannerCacheConfig bannerCacheConfig;
        
        List<CacheConfig> configList = model.getCacheConfigList();
        
        if (null == configList || configList.isEmpty())
        {
            return this;
        }
        
        //缓存配置总开关
        this.enableLocalMemCache = model.isEnableCache();
        this.preLoadRate = model.getPreLoadRate();
        this.enableLocalDBCache = model.isEnableLocalDBCache();
        this.enableLog = model.isEnableLog();
        this.enablePreLoad = model.isEnablePreLoad();
        
        //更新日志开关
        if (this.enableLog != Logger.isLog)
        {
            Logger.updateLogEnable(this.enableLog);
        }
        
        String tmpType = null;
        
        for (CacheConfig cfg : configList)
        {
            tmpType = cfg.getType();
            //栏目缓存数据
            if ("category".equals(tmpType))
            {
                categoryCacheCfg.setEnableMemCache(cfg.isEnable());
                categoryCacheCfg.setExpireTime(cfg.getExpireTime());
                categoryCacheCfg.setEnableLocalDBCache(cfg.isEnableDB());
            }
            //首页底部广告栏缓存
            else if ("adBanner".equals(tmpType))
            {
                bannerCacheConfig.setEnableMemCache(cfg.isEnable());
                bannerCacheConfig.setExpireTime(cfg.getExpireTime());
                bannerCacheConfig.setEnableLocalDBCache(cfg.isEnableDB());
            }
            //每日消息缓存
            else if ("dayMsg".equals(tmpType))
            {
                dayMsgCacheConfig.setEnableMemCache(cfg.isEnable());
                dayMsgCacheConfig.setExpireTime(cfg.getExpireTime());
                dayMsgCacheConfig.setEnableLocalDBCache(cfg.isEnableDB());
            }
            //Mall directory 目录促销缓存
            else if ("promotion".equals(tmpType))
            {
                promotionCacheConfig.setEnableMemCache(cfg.isEnable());
                promotionCacheConfig.setExpireTime(cfg.getExpireTime());
                promotionCacheConfig.setEnableLocalDBCache(cfg.isEnableDB());
            }
            // myAccount 缓存
            else if ("myAccount".equals(tmpType))
            {
                myAccountCacheConfig.setEnableMemCache(cfg.isEnable());
                myAccountCacheConfig.setExpireTime(cfg.getExpireTime());
                myAccountCacheConfig.setEnableLocalDBCache(cfg.isEnableDB());
            }
            //产品独立类型缓存设置(首页挂牌数据缓存)
            else if (-1 != "newarrival|topsellers|gadgets|Clearance|mvp|latestdiscount|spotlight".indexOf(tmpType))
            {
            	//Type字符转换 保证跟存储字符一样 by huangfei 20150526
            	if("newarrival".equals(tmpType)){
            		tmpType=Constant.TYPE_NEWARRIVALS;
            	}else if("topsellers".equals(tmpType)){
            		tmpType=Constant.TYPE_TOPSELLERS;
            	}
            	else if("latestdiscount".equals(tmpType)){
//            		tmpType=Constant.TYPE_LATESTDISCOUNT;
                    // TODO: 2017/7/17 后期需要把这个Latestdiscount修改为us仓的地址
                    tmpType = Constant.TYPE_USWAREHOUSE;
                }
            	else if("spotlight".equals(tmpType)){
            		tmpType=Constant.TYPE_SPORTLIGHTS;
            	}
            	else if("mvp".equals(tmpType)){
            		tmpType=Constant.TYPE_MVP24HRS;
            	}
                productCacheCfg.getConfigMapping().put(tmpType, cfg);
                productCacheCfg.setEnableLocalDBCache(cfg.isEnableDB());
            }
            //TODO待服务端补充
            //日志行为/监控 配置
            else if ("enableMonitor".equals(tmpType))
            {
                ConfigUtil.getInstance().getConfig().getLogConfig().setEnableMonitor(cfg.isEnable());
            }
            //其它类型忽略
            //            else
            //            {
            //                
            //            }
            
        }
        return this;
    }
    
    //内存状态监测: 在低内存状态或低内存设备上将停用内存缓存
    private boolean checkMemory()
    {
        return true;
    }
    
    //监测数据库状态: 一些设备场景下将不会支持数据缓存操作
    private boolean checkLocalDB()
    {
        return true;
    }
    
    //[start]
    /**
     * 首页广告缓存配置
     * @author Administrator
     *
     */
    static class BannerCacheConfig extends BaseCfg
    {
        
    }
    
    /**
     * Mall Directory 广告促销缓存配置
     * @author Administrator
     *
     */
    static class PromotionCacheConfig extends BaseCfg
    {
        
    }
    
    /**
     * 我的账号信息缓存配置            
     * @author Administrator
     *
     */
    static class MyAccountCacheConfig extends BaseCfg
    {
        
    }
    
    /**
     * 每日消息信息缓存配置            
     * @author Administrator
     *
     */
    static class DayMsgCacheConfig extends BaseCfg
    {
        
    }
    
    /**
     * 配置基础类    
     * @author Administrator
     *
     */
    static class BaseCfg
    {
        /**
         * 是否允许缓存(默认：true)
         */
        private boolean enableMemCache = true;
        
        /**
         * 缓存失效时长(单位: 毫秒，默认3分钟秒)
         */
        private int expireTime = 3 * 60 * 1000;
        
        /**
         * 是否允许本地数据库缓存(默认：true)
         */
        private boolean enableLocalDBCache = true;
        
        boolean isEnableLocalDBCache()
        {
            return enableLocalDBCache;
        }
        
        void setEnableLocalDBCache(boolean enableLocalDBCache)
        {
            this.enableLocalDBCache = enableLocalDBCache;
        }
        
        public boolean isEnableMemCache()
        {
            return enableMemCache;
        }
        
        void setEnableMemCache(boolean enableMemCache)
        {
            this.enableMemCache = enableMemCache;
        }
        
        public int getExpireTime()
        {
            return expireTime;
        }
        
        void setExpireTime(int expireTime)
        {
            this.expireTime = expireTime;
        }
    }
    //[end]
}
